package org.news.web.controller.app;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.util.ObjectUtil;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dtflys.forest.annotation.Get;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.system.domain.vo.SysOssUploadVo;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.service.ISysOssService;
import org.news.web.constant.ApplyCreatorsConstant;
import org.news.web.constant.AuthorInfo;
import org.news.web.constant.CategoriesStatus;
import org.news.web.constant.NewsConstant;
import org.news.web.domain.*;
import org.news.web.domain.bo.*;
import org.news.web.domain.vo.*;
import org.news.web.mapper.*;
import org.news.web.service.*;
import org.news.web.service.impl.CategoriesServiceImpl;
import org.news.web.service.impl.CreatorsServiceImpl;
import org.news.web.service.impl.NewsServiceImpl;
import org.news.web.utils.UserInfoInterceptorUtils;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/app/user")
@SaIgnore
public class UserController {

    private final IHistoryService historyService;

    private final IFavoritesService favoritesService;

    private final HistoryMapper historyMapper;

    private final FavoritesMapper favoritesMapper;

    private final NewsMapper newsMapper;


    private final INewsService newsService;

    private final NewsServiceImpl newsServiceImpl;


    private final ISubscriptionsService subscriptionsService;


    private final ICreatorsService creatorsService;

    private final CreatorsMapper creatorsMapper;

    private final CreatorsServiceImpl creatorsServiceImpl;

    private final ICategoriesService categoriesService;


    private final CategoriesMapper categoriesMapper;

    private final CategoriesServiceImpl categoriesServiceImpl;

    private final ITagsService tagsService;

    private final ISysOssService ossService;

    private final IApplyCreatorsService applyCreatorsService;

    private final INotificationsService notificationsService;

    private final ILikesService likesService;

    private final LikesMapper likesMapper;

    private final UsersMapper usersMapper;

    private final  ICommentsService commentsService;

    private final  CommentsMapper commentsMapper;


    //获取历史记录
    @GetMapping("/history")
    public R<TableDataInfo> history(HttpServletRequest request,HistoryBo historyBo,PageQuery pageQuery){
        Boolean aBoolean = UserInfoInterceptorUtils.CheckUserInfoKey(request);
        if(aBoolean){
//            获取用户的历史记录
            Long userId = UserInfoInterceptorUtils.getUserId(request);
            historyBo.setUserId(userId);
            pageQuery.setIsAsc("desc");
            pageQuery.setOrderByColumn("actionTime");
            TableDataInfo<HistoryVo> historyVoTableDataInfo = historyService.queryPageList(historyBo, pageQuery);
//
            Set<Long> collect = historyVoTableDataInfo.getRows().stream().map(HistoryVo::getNewsId).collect(Collectors.toSet());

            if(collect != null && collect.size()>0){
                List<NewsVo> news = newsMapper.selectVoList(new LambdaQueryWrapper<News>().in(News::getNewsId, collect));
                newsServiceImpl.setNewsAuthorName(news);
                newsService.setNewsImg(news);


                historyVoTableDataInfo.getRows().forEach( item ->{
                    news.stream().forEach(newsVo -> {
                        if(item.getNewsId().longValue() == newsVo.getNewsId().longValue()){
                            item.setNewsVo(newsVo);
                        }
                    });
                });
            }
            return R.ok(historyVoTableDataInfo);
        }else{
            return R.fail("nouser");
        }
    }

    //删除当前记录
    @GetMapping("/del/history/{id}")
    public R<Boolean> clearHistory(HttpServletRequest request, @PathVariable Long id){
        Boolean aBoolean = UserInfoInterceptorUtils.CheckUserInfoKey(request);
        if(aBoolean) {
            Long userId = UserInfoInterceptorUtils.getUserId(request);

            History history = new History();
            history.setUserId(userId);
            history.setHistoryId(id);
            int i = historyMapper.deleteById(history);

            return R.ok(i>0);
        }else{
            return R.fail("nouser");
        }

    }
    //删除当前所有记录
    @GetMapping("/delAll/history")
    public R<Boolean> clearAllHistory(HttpServletRequest request){
        Boolean aBoolean = UserInfoInterceptorUtils.CheckUserInfoKey(request);
        if(aBoolean) {
            Long userId = UserInfoInterceptorUtils.getUserId(request);
            int i = historyMapper.delete(new LambdaQueryWrapper<History>().eq(History::getUserId,userId));
            return R.ok(i>0);
        }else{
            return R.fail("nouser");
        }
    }

    //获取收藏
    @GetMapping("/favo")
    public R<TableDataInfo> favo(HttpServletRequest request, FavoritesBo favoritesVo, PageQuery pageQuery){
        Boolean aBoolean = UserInfoInterceptorUtils.CheckUserInfoKey(request);
        if(aBoolean) {
            Long userId = UserInfoInterceptorUtils.getUserId(request);


            favoritesVo.setUserId(userId);
            pageQuery.setIsAsc("desc");
            pageQuery.setOrderByColumn("creationTime");
            TableDataInfo<FavoritesVo> favoritesVoTableDataInfo = favoritesService.queryPageList(favoritesVo, pageQuery);
//
            Set<Long> collect = favoritesVoTableDataInfo.getRows().stream().map(FavoritesVo::getNewsId).collect(Collectors.toSet());

            if(collect != null && collect.size()>0) {
                List<NewsVo> news = newsMapper.selectVoList(new LambdaQueryWrapper<News>().in(News::getNewsId, collect));
                newsServiceImpl.setNewsAuthorName(news);
                newsService.setNewsImg(news);


                favoritesVoTableDataInfo.getRows().forEach( item ->{
                    news.stream().forEach(newsVo -> {
                        if(item.getNewsId().longValue() == newsVo.getNewsId().longValue()){
                            item.setNewsVo(newsVo);
                        }
                    });
                });
            }
            return R.ok(favoritesVoTableDataInfo);
        }else{
            return R.fail("nouser");
        }
    }



    //我的关注
    @GetMapping("/myFollow")
    public R<TableDataInfo> myFollow(HttpServletRequest request, SubscriptionsBo subscriptionsbo, PageQuery pageQuery){
        Boolean aBoolean = UserInfoInterceptorUtils.CheckUserInfoKey(request);
        if(aBoolean) {
            Long userId = UserInfoInterceptorUtils.getUserId(request);
            pageQuery.setIsAsc("desc");
            pageQuery.setOrderByColumn("creationTime");
            subscriptionsbo.setSubscriberId(userId);
            TableDataInfo<SubscriptionsVo> subscriptionsVoTableDataInfo = subscriptionsService.queryPageList(subscriptionsbo, pageQuery);
//           收集栏目和作者id
            Set<Long> cts = subscriptionsVoTableDataInfo.getRows().stream().filter(item -> {
                return item.getStatus() == 2;
            }).map(SubscriptionsVo::getTargetCategoryId).collect(Collectors.toSet());
            if(cts != null && cts.size()>0){
                List<CreatorsVo> creators = creatorsMapper.selectVoList(new LambdaQueryWrapper<Creators>().in(Creators::getCreatorId, cts));
                creatorsServiceImpl.setImgName(creators);

                subscriptionsVoTableDataInfo.getRows().forEach(item ->{
                    creators.stream().forEach(
                        creatorsVo -> {
                            if(creatorsVo.getCreatorId() == item.getTargetCategoryId() && item.getStatus() == 2){
                                item.setCreatorsVo(creatorsVo);
                            }
                        }
                    );
                });
            }
            Set<Long> lms = subscriptionsVoTableDataInfo.getRows().stream().filter(item -> {
                return item.getStatus() == 1;
            }).map(SubscriptionsVo::getTargetCategoryId).collect(Collectors.toSet());
            if(lms != null && lms.size()>0){
                List<CategoriesVo> categoriesVos = categoriesMapper.selectVoList(new LambdaQueryWrapper<Categories>().in(Categories::getCategoryId, lms));
                categoriesServiceImpl.setImg(categoriesVos);

                subscriptionsVoTableDataInfo.getRows().forEach(item ->{
                    categoriesVos.stream().forEach(
                        categoriesVo -> {
                            if(categoriesVo.getCategoryId() == item.getTargetCategoryId() && item.getStatus() == 1){
                                item.setCategoriesVo(categoriesVo);
                            }
                        }
                    );
                });
            }
            return R.ok(subscriptionsVoTableDataInfo);
        }else{
            return R.fail("nouser");
        }
    }

    /**
     * 标签模糊查询
     * @param bo
     * @param pageQuery
     * @return
     */
    @GetMapping("/getListTags")
    public TableDataInfo<TagsVo> getListTags(TagsBo bo, PageQuery pageQuery) {
        return tagsService.getListTags(bo, pageQuery);
    }


    /**
     *  选择类别
     */
    @GetMapping("/getListLbCategories")
    public TableDataInfo<CategoriesVo> getListLbCategories(AuthorInfo bo, PageQuery pageQuery) {
        return categoriesService.getListLbCategories(bo, pageQuery);
    }

    /**
     * oos 上传
     * @param file
     * @return
     */
    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public R<SysOssUploadVo> upload(@RequestPart("file") MultipartFile file) {
        if (ObjectUtil.isNull(file)) {
            return R.fail("上传文件不能为空");
        }
        SysOssVo oss = ossService.upload(file);
        SysOssUploadVo uploadVo = new SysOssUploadVo();
        uploadVo.setUrl(oss.getUrl());
        uploadVo.setFileName(oss.getOriginalName());
        uploadVo.setOssId(oss.getOssId().toString());
        return R.ok(uploadVo);
    }


    @PostMapping("/createNews")
    public R<Boolean> createNews(@RequestBody NewsBo bo) throws UnsupportedEncodingException, ClientException {
        return R.ok(newsService.insertByBo(bo));
    }



    @GetMapping("/getCreatorInfo/{userId}")
    public R<CreatorsVo> getInfo(@PathVariable Long userId){
        return R.ok(creatorsMapper.selectVoOne(new LambdaQueryWrapper<Creators>().eq(Creators::getUserId, userId)));
    }



    /**
     * 获取新闻审核类型
     */
    @GetMapping("/getShenHe")
    public R<List<CategoriesStatus>> getShenHe(){
        return R.ok(NewsConstant.NEWS_SHEN_HE);
    }


    /**
     * 提交审核
     */
    @GetMapping("/creator/apply")
    public R<Void> creatorApply(HttpServletRequest request,String content){
        Boolean aBoolean = UserInfoInterceptorUtils.CheckUserInfoKey(request);
        if(aBoolean) {
            Long userId = UserInfoInterceptorUtils.getUserId(request);
            ApplyCreatorsBo applyCreatorsBo = new ApplyCreatorsBo();
            applyCreatorsBo.setUserId(userId);
            applyCreatorsBo.setApplicationStatus(ApplyCreatorsConstant.DAI_APPLY);
            applyCreatorsBo.setApplicationInfo(content);
            applyCreatorsService.insertByBo(applyCreatorsBo);
            return R.ok();
        }else{
            return R.fail("nouser");
        }
    }


    /**
     * 我的粉丝
     */
    @GetMapping("/getMyFans")
    public TableDataInfo<SubscriptionsVo> getListLbCategories(SubscriptionsBo bo, PageQuery pageQuery) {
        return subscriptionsService.queryPageList(bo,pageQuery);
    }

    /**
     * 通知
     */

    @GetMapping("/notification/list")
    public TableDataInfo<NotificationsVo> notificationList(NotificationsBo bo, PageQuery pageQuery) {
        return notificationsService.queryPageList(bo, pageQuery);
    }

    /**
     * 点赞通知
     */

    @GetMapping("/like/list")
    public TableDataInfo<LikesVo> likeList(LikesBo bo, PageQuery pageQuery) {
        //获取该用户的作者信息
        Long userId = bo.getUserId();
        CreatorsVo creators = creatorsMapper.selectVoOne(new LambdaQueryWrapper<Creators>().eq(Creators::getUserId, userId));
        if(creators == null){
            return null;
        }
        //通过作者信息查询到作者发布的所有文章id信息
        List<News> news = newsMapper.selectList(new LambdaQueryWrapper<News>().eq(News::getAuthorType, NewsConstant.CREATORS_CODE).eq(News::getApplyStatus, NewsConstant.FaBu).eq(News::getAuthor, creators.getCreatorId()));
        if(news == null || news.size() == 0){
            return null;
        }
        Set<Long> newsIds = news.stream().map(News::getNewsId).collect(Collectors.toSet());
        //通过新闻id获取所有给这些新闻点赞的用户 在进行排序
        LambdaQueryWrapper<Likes> likesLambdaQueryWrapper = new LambdaQueryWrapper<>();
        likesLambdaQueryWrapper.in(Likes::getNewsId,newsIds);
        Page<LikesVo> result  = likesMapper.selectVoPage(pageQuery.build(), likesLambdaQueryWrapper);
//        设置用户名
        if(ObjectUtil.isNotNull(result.getRecords()) && result.getRecords().size() >0){
            Set<Long> collect = result.getRecords().stream().map(item -> {
                return item.getUserId();
            }).collect(Collectors.toSet());

            List<UsersVo> users = usersMapper.selectVoList(new LambdaQueryWrapper<Users>().in(Users::getUserId, collect));
//          设置img
            List<Long> pcs = users.stream().map(item ->{
                return Long.valueOf(item.getProfilePicture()).longValue();
            }).toList();
            List<SysOssVo> sysOssVos = ossService.listByIds(pcs);

            users.forEach(
                user->{
                    for (SysOssVo sysOssVo : sysOssVos) {
                        if(Long.valueOf(user.getProfilePicture()).longValue() == sysOssVo.getOssId().longValue()){
                            user.setPictureUrl(sysOssVo.getUrl());
                            break;
                        }
                    }
                }
            );

            users.forEach(user ->{
                result.getRecords().stream().forEach(item ->{
                    if(item.getUserId() == user.getUserId()){
                        item.setUsersVo(user);
                    }
                });
            });
        }

//      把新闻相关信息加入到其中
        if(result.getRecords().size() >0){
            result.getRecords().stream().forEach(
                item->{
                    news.stream().forEach(
                        newsItem ->{
                            if(item.getNewsId() == newsItem.getNewsId()){
                                item.setNews(newsItem);
                            }
                        }
                    );
                }
            );
        }
        return TableDataInfo.build(result);
    }


    /**
     * 评论通知
     */
    @GetMapping("/comment/list")
    public TableDataInfo<CommentsVo> commentsList(CommentsBo bo, PageQuery pageQuery){
        // 1.获取自己的所有评论信息id
        Long userId = bo.getUserId();
        List<CommentsVo> commentsVos = commentsMapper.selectVoList(new LambdaQueryWrapper<Comments>().eq(Comments::getUserId, userId));
        if(commentsVos==null || commentsVos.size() == 0){
            return null;
        }
        Set<Long> collect = commentsVos.stream().map(CommentsVo::getCommentId).collect(Collectors.toSet());
        if(collect==null || collect.size() == 0){
            return null;
        }
        //2.通过自己的id寻找自己的子id 把子id进行排序
        LambdaQueryWrapper<Comments> commentsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        commentsLambdaQueryWrapper.in(Comments::getParentCommentId,collect);
        Page<CommentsVo> result = commentsMapper.selectVoPage(pageQuery.build(), commentsLambdaQueryWrapper);

        // 需要用户信息 评论信息 和 新闻信息
//        设置子评论的用户信息
        if(ObjectUtil.isNotNull(result.getRecords()) && result.getRecords().size() >0){
            Set<Long> collect1 = result.getRecords().stream().map(item -> {
                return item.getUserId();
            }).collect(Collectors.toSet());

            List<UsersVo> users = usersMapper.selectVoList(new LambdaQueryWrapper<Users>().in(Users::getUserId, collect1));
//          设置img
            List<Long> pcs = users.stream().map(item ->{
                return Long.valueOf(item.getProfilePicture()).longValue();
            }).toList();
            List<SysOssVo> sysOssVos = ossService.listByIds(pcs);

            users.forEach(
                user->{
                    for (SysOssVo sysOssVo : sysOssVos) {
                        if(Long.valueOf(user.getProfilePicture()).longValue() == sysOssVo.getOssId().longValue()){
                            user.setPictureUrl(sysOssVo.getUrl());
                            break;
                        }
                    }
                }
            );

            users.forEach(user ->{
                result.getRecords().stream().forEach(item ->{
                    if(item.getUserId() == user.getUserId()){
                        item.setUsersVo(user);
                    }
                });
            });
        }
//        设置自己的父评论信息
        if(ObjectUtil.isNotNull(result.getRecords()) && result.getRecords().size() >0){
            result.getRecords().forEach(item ->{
                for (CommentsVo commentsVo : commentsVos) {
                    if(item.getParentCommentId() == commentsVo.getCommentId()){
                        item.setCommentsVo(commentsVo);
                        break;
                    }
                }
            });
        }
//        设置新闻信息
        if(ObjectUtil.isNotNull(result.getRecords()) && result.getRecords().size() >0){
//            查看这些result 的新闻数据
            Set<Long> newsIds = result.getRecords().stream().map(CommentsVo::getNewsId).collect(Collectors.toSet());
            List<NewsVo> news = newsMapper.selectVoList(new LambdaQueryWrapper<News>().in(News::getNewsId, newsIds));
            result.getRecords().forEach(item ->{
                for (NewsVo news1 : news) {
                    if(item.getNewsId() == news1.getNewsId()){
                        item.setNewsVo(news1);
                        break;
                    }
                }
            });
        }

        return TableDataInfo.build(result);
    }








}
